package com.xxlie.auth.security.endpoint;

import com.xxlie.auth.common.CommUtil;
import com.xxlie.auth.domain.User;
import com.xxlie.auth.security.auth.AjaxAuthenticationToken;
import com.xxlie.auth.security.auth.ajax.AjaxAwareAuthenticationSuccessHandler;
import com.xxlie.auth.security.auth.ajax.RegisterPhoneRequest;
import com.xxlie.auth.security.auth.ajax.RegisterRequest;
import com.xxlie.auth.security.auth.ajax.ResetRequest;
import com.xxlie.auth.security.auth.ajax.RoleTypeEnum;
import com.xxlie.auth.service.RoleService;
import com.xxlie.auth.service.UserService;
import com.xxlie.core.common.ValidateUtil;
import com.xxlie.core.model.View;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * 注册
 *
 *
 * @author xxlie.com
 * @since 2017/8/6
 */
@RestController
public class RegisterEndpoint {

    @Autowired
    private UserService userService;
    @Autowired
    private RoleService roleService;

    @Autowired
    private PasswordEncoder encoder;

    @Autowired
    @Lazy
    private AuthenticationManager authenticationManager;

    @Autowired
    CommUtil commUtil;

    @Autowired
    @Lazy
    private AjaxAwareAuthenticationSuccessHandler ajaxAwareAuthenticationSuccessHandler;

    @RequestMapping(value = "/api/auth/register")
    public View<User> registerUser(@Validated @RequestBody RegisterRequest register) {

        String pwd = encoder.encode(register.getPassword());
        register.setPassword(pwd);
        User user = new User(register);

        if (user.getRole() == null) {
            user.setRole(roleService.findPositionByEnName(RoleTypeEnum.GENERAL.getCode()));
        }

        userService.save(user);
        View<User> view = View.ofOk();
        view.setData(user);
        return view;
    }

    @RequestMapping(value = "/api/auth/register/phone")
    public View registerUserByPhone(HttpServletRequest request, HttpServletResponse response, @Validated @RequestBody RegisterPhoneRequest register, BindingResult result) {
        if (result.hasErrors()) {
            return View.ofError(ValidateUtil.first(result.getAllErrors()));
        }

        //校验短信验证码是否正确
        boolean checkResult = commUtil.validateSmsCode(register.getPhone(), register.getSmsCode());
        if (!checkResult) {
            return View.ofError("验证码错误");
        }
        //检查手机号是否已经注册了
        Optional<User> isExistPhone = this.userService.findByPhone(register.getPhone());
        if (isExistPhone.isPresent()) {
            return View.ofError("该手机号已注册");
        }
        //检查手机号是否已经注册为用户名了
        Optional<User> isExistUsername = this.userService.getByUsername(register.getUsername());
        if (isExistUsername.isPresent()) {
            return View.ofError("该用户名已存在");
        }

        //处理密码
        String pwd = encoder.encode(register.getPassword());
        register.setPassword(pwd);
        User user = new User(register);

        //添加角色
        user.setRole(roleService.findPositionByEnName(RoleTypeEnum.OTHER.getCode()));

        //随机生成用户名
        user.setNickName("菜鸟" + CommUtil.randomInt(6));

        //保存用户
        userService.save(user);

        Map extraParams = new HashMap();
        extraParams.put("source", 1);

        //注册成功，立即进行登录
        AjaxAuthenticationToken token = new AjaxAuthenticationToken(register.getPhone(), register.getSmsCode(), extraParams);
        token.setDetails(new WebAuthenticationDetails(request));
        Authentication authenticatedUser = authenticationManager.authenticate(token);

        return ajaxAwareAuthenticationSuccessHandler.getSecurityToken(authenticatedUser);
        
//        return View.ofOk("注册成功");
    }

    @RequestMapping(value = "/api/auth/reset")
    public View userReset(HttpServletRequest request, HttpServletResponse response, @Validated @RequestBody ResetRequest resetRequest, BindingResult result) {
        if (result.hasErrors()) {
            return View.ofError(ValidateUtil.first(result.getAllErrors()));
        }

        //校验短信验证码是否正确
        boolean checkResult = commUtil.validateSmsCode(resetRequest.getPhone(), resetRequest.getSmsCode());
        if (!checkResult) {
            return View.ofError("验证码错误");
        }
        //检查手机号是否已经注册了
        Optional<User> isExistPhone = this.userService.findByPhone(resetRequest.getPhone());
        if (!isExistPhone.isPresent()) {
            return View.ofError("该手机号未注册");
        }

        //处理密码
        String pwd = encoder.encode(resetRequest.getPassword());
        resetRequest.setPassword(pwd);

        Optional<User> user = this.userService.findByPhone(resetRequest.getPhone());

        User saveUser = user.get();
        saveUser.setPassword(pwd);

        //保存用户
        userService.save(saveUser);

        Map extraParams = new HashMap();
        extraParams.put("source", 1);

        //注册成功，立即进行登录
        AjaxAuthenticationToken token = new AjaxAuthenticationToken(resetRequest.getPhone(), resetRequest.getSmsCode(), extraParams);
        token.setDetails(new WebAuthenticationDetails(request));
        Authentication authenticatedUser = authenticationManager.authenticate(token);

        try {
            ajaxAwareAuthenticationSuccessHandler.onAuthenticationSuccess(request, response, authenticatedUser);
        } catch (IOException ioe) {
            return View.ofError("修改失败");
        } catch (ServletException se) {
            return View.ofError("修改失败");
        }
        return View.ofOk("修改成功");
    }

}
